package com.gpj.learn.netty.reactor.single.handler;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

public class IOHandler implements Runnable {
    private final SelectionKey selectionKey;
    private final SocketChannel socketChannel;

    private String text;
    private int state; // 0-reading，1-writing

    public IOHandler(SelectionKey selectionKey, SocketChannel socketChannel) {
        this.selectionKey = selectionKey;
        this.socketChannel = socketChannel;
        // 初始化状态
        state = 0;
    }

    @Override
    public void run() {
        try {
            if (state == 0)
                read();
            else
                send();
        } catch (IOException e) {
            closeChannel();
        }
    }

    private void closeChannel() {
        try {
            System.out.println("[Warning!] A client has been closed.");
            selectionKey.cancel();
            socketChannel.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    private synchronized void read() throws IOException {
        byte[] arr = new byte[1024];
        ByteBuffer buf = ByteBuffer.wrap(arr);
        buf.clear();

        int numBytes = socketChannel.read(buf);
        if(numBytes == -1) {
            closeChannel();
            return;
        }

        byte[] byteArr = new byte[buf.position()];
        for (int i = 0; i < buf.position(); i++) {
            byteArr[i] = buf.get(i);
        }

        text = new String(byteArr);
        text = text.replace("\\n", "");
        if ((text != null) && !text.equals(" ")) {
            // 业务处理...

            System.out.println(socketChannel.socket().getRemoteSocketAddress().toString()
                    + " > " + text);
            // 改变状态
            state = 1;
            // 改变注册事件
            selectionKey.interestOps(SelectionKey.OP_WRITE);
            selectionKey.selector().wakeup();
        }
    }

    private void send() throws IOException  {
        String str = "收到信息: "
                + socketChannel.socket().getLocalSocketAddress().toString() + " > " + text;
        ByteBuffer buf = ByteBuffer.wrap(str.getBytes());

        while (buf.hasRemaining()) {
            socketChannel.write(buf);
        }

        state = 0;
        selectionKey.interestOps(SelectionKey.OP_READ);
        selectionKey.selector().wakeup();
    }
}